package top.hmtools.jsCss.srcManager;

import java.io.IOException;
import java.io.InputStream;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Set;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.io.FilenameUtils;
import org.apache.commons.io.IOUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.util.AntPathMatcher;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.servlet.HandlerMapping;

import top.hmtools.base.StringTools;
import top.hmtools.conversion.Extension2MimeTools;
import top.hmtools.jsCss.autoConfiguration.JsCssAutoConfiguration;

/**
 * 通用获取静态资源文件
 * @author Hybomyth
 *
 */
@Controller
//@ConditionalOnBean(value=IsEnableJsCss.class)
public class SrcController {
	private final Logger logger = LoggerFactory.getLogger(SrcController.class);
	
	@Autowired
	private JsCssAutoConfiguration jsCssAutoConfiguration;

	/**
	 * 通用的获取静态资源文件（单个，并且最好指定有文件后缀名的）
	 * @param srcName
	 * @param request
	 * @param response
	 */
	@RequestMapping(value="#{'${"+JsCssAutoConfiguration.src_uri+":}'?:'/src'}/**/{srcName}",method={RequestMethod.GET})
	public void getSrc(@PathVariable(value="srcName")String srcName,HttpServletRequest request,HttpServletResponse response){
		srcName = this.extractPathFromPattern(request);
		this.logger.debug("当前请求的静态资源是：{}",srcName);
		
		//验证请求资源合法性（即在配置监控的路径下，防止重要文件被泄露）
		String cssFilesPaths = this.jsCssAutoConfiguration.getCssFilesPaths();
		String jsFilesPaths = this.jsCssAutoConfiguration.getJsFilesPaths();
		if(StringTools.isAllBlank(cssFilesPaths,jsFilesPaths)){
			try {
				response.sendError(HttpServletResponse.SC_NOT_FOUND);
			} catch (IOException e) {
			}
			return;
		}
		Set<String> srcPaths = new HashSet<String>();
		if(StringTools.isNotBlank(cssFilesPaths)){
			String[] cssPathsArr = cssFilesPaths.split(",");
			srcPaths.addAll(Arrays.asList(cssPathsArr));
		}
		if(StringTools.isNotBlank(jsFilesPaths)){
			String[] jsPathsArr = jsFilesPaths.split(",");
			srcPaths.addAll(Arrays.asList(jsPathsArr));
		}
		this.logger.debug("合法的根路径有：{}",srcPaths);
		boolean isSrcValideOK=false;
		for(String root:srcPaths){
			boolean startsWith = srcName.startsWith(root);
			if(startsWith){
				isSrcValideOK=true;
				break;
			}
		}
		if(!isSrcValideOK){
			try {
				response.sendError(HttpServletResponse.SC_NOT_FOUND);
			} catch (IOException e) {
			}
			return;
		}
		
		//获取静态资源文件输入流
		InputStream inputStream = Thread.currentThread().getContextClassLoader().getResourceAsStream(srcName);
		ServletOutputStream outputStream = null;
		try {
			if(inputStream == null){
				response.sendError(HttpServletResponse.SC_NOT_FOUND);
				return;
			}
			
			//发送数据
			response.reset();
			response.setBufferSize(2048);
			try {
				String extension = FilenameUtils.getExtension(srcName);
				String mime = Extension2MimeTools.getMimeByExtension(extension);
				response.setContentType(mime);
			} catch (Exception e) {
			}
			outputStream = response.getOutputStream();
			long contentLength = IOUtils.copyLarge(inputStream, outputStream);
			response.setStatus(HttpServletResponse.SC_OK);
			response.setContentLengthLong(contentLength);
		} catch (IOException e) {
			logger.error("获取静态资源文件失败："+e.getMessage(),e);
			try {
				response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR,e.getMessage());
			} catch (IOException e1) {
				this.logger.error(e1.getMessage(),e1);
			}
		}finally{
			if(inputStream != null){
				try {
					inputStream.close();
				} catch (IOException e) {
					logger.error("关闭静态资源文件失败："+e.getMessage(),e);
				}
			}
			if(outputStream != null){
				try {
					outputStream.close();
				} catch (IOException e) {
					logger.error("关闭输出流失败："+e.getMessage(),e);
				}
			}
		}
	}
	
	/**
	 * 处理@PathVariable URL中的“/”
	 * @param request
	 * @return
	 */
	private String extractPathFromPattern(final HttpServletRequest request) {
		String path = (String) request.getAttribute(HandlerMapping.PATH_WITHIN_HANDLER_MAPPING_ATTRIBUTE);
		String bestMatchPattern = (String) request.getAttribute(HandlerMapping.BEST_MATCHING_PATTERN_ATTRIBUTE);
		return new AntPathMatcher().extractPathWithinPattern(bestMatchPattern, path);
	}
}
